package com.john.pplay.activity;

import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;

import com.john.pplay.util.Circle;
import com.john.pplay.common.IPlayerListener;
import com.john.pplay.util.MeasureHelp;
import com.john.pplay.util.MsgCode;
import com.john.pplay.util.MyLog;
import com.john.pplay.common.PlayerListener;
import com.john.pplay.R;
import com.john.pplay.util.Position;
import com.john.pplay.util.Setting;

import net.lemonsoft.lemonhello.LemonHello;
import net.lemonsoft.lemonhello.LemonHelloAction;
import net.lemonsoft.lemonhello.LemonHelloInfo;
import net.lemonsoft.lemonhello.LemonHelloView;
import net.lemonsoft.lemonhello.interfaces.LemonHelloActionDelegate;

import java.io.IOException;
import java.util.Locale;

import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;

public class VideoActivity extends BaseActivity implements View.OnClickListener {

    private final String TAG = "VideoActivity";
    private final long CLICK_TIMEOUT = 300;
    private SurfaceView surfaceView;
    private Circle bufferView;
    private TextView messageView;
    private LinearLayout lytSeek;
    private TextView tvCurrentPosition;
    private TextView tvDuration;
    private SeekBar seekBar;
    private IMediaPlayer mediaPlayer;
    private String videoPath;
    private Uri videoURI;
    private Handler myHandler;
    private IPlayerListener listener;
    private long timeStamp;
    private long duration;
    private long currentTime;
    private MeasureHelp measureHelp;
    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        this.setContentView(R.layout.activity_main);
        myHandler = new MyHandler();
        listener = new PlayerListener(myHandler);

        measureHelp = new MeasureHelp(this.getApplicationContext());
        measureHelp.setType(Setting.getInstance().getMeasureType());

        surfaceView = (SurfaceView)findViewById(R.id.play_view);
        surfaceView.setOnClickListener(this);
        surfaceView.setKeepScreenOn(true);
        surfaceView.getHolder().addCallback(new  SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {
                myHandler.sendEmptyMessage(MsgCode.INIT);
            }
            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { }
            @Override
            public void surfaceDestroyed(SurfaceHolder surfaceHolder) { }
        });
        surfaceView.setOnTouchListener(touchListener);

        bufferView = (Circle)findViewById(R.id.buffer_view);
        messageView = (TextView)findViewById(R.id.message_view);
        lytSeek = (LinearLayout)findViewById(R.id.lyt_seek);
        tvCurrentPosition = (TextView)findViewById(R.id.tv_current_position);
        tvDuration = (TextView)findViewById(R.id.tv_duration);
        seekBar = (SeekBar)findViewById(R.id.seekBar);
        lytSeek.setVisibility(View.GONE);
//        videoPath = "http://ivi.bupt.edu.cn/hls/cctv5hd.m3u8";
//        videoPath = "http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_16x9/gear5/prog_index.m3u8";
//        videoPath = "http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear2/prog_index.m3u8";
        videoPath = getIntent().getStringExtra("videoPath");
        if (getIntent().getData() != null ){
            videoURI = getIntent().getData();
        }

    }

    @Override
    protected void onPause(){
        if (null != mediaPlayer){
            mediaPlayer.pause();
            mediaPlayer.stop();
            mediaPlayer.release();
        }
        super.onPause();
    }

    private void initPlayer(){
        mediaPlayer = new IjkMediaPlayer();
        try {
            if (videoPath != null){
                mediaPlayer.setDataSource(videoPath);
            }else if (videoURI != null){
                mediaPlayer.setDataSource(this,videoURI);
            }else{
                return;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }

        IjkMediaPlayer ijkMediaPlayer = (IjkMediaPlayer)mediaPlayer;
        ijkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_WARN);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", Setting.getInstance().getDecodeType());
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 1);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 0);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV16);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);

        mediaPlayer.setDisplay(surfaceView.getHolder());
        mediaPlayer.setOnPreparedListener(listener);
        mediaPlayer.setOnBufferingUpdateListener(listener);
        mediaPlayer.setOnCompletionListener(listener);
        mediaPlayer.setOnErrorListener(listener);
        mediaPlayer.setOnInfoListener(listener);
        mediaPlayer.setOnSeekCompleteListener(listener);

        mediaPlayer.prepareAsync();
    }
    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();

    @Override
    public void onClick(View view) {
        long now = System.currentTimeMillis();
        if (now - timeStamp <= CLICK_TIMEOUT) {
            if (view == surfaceView && mediaPlayer != null) {
                if (mediaPlayer.isPlaying()) {
                    mediaPlayer.pause();
                } else {
                    mediaPlayer.start();
                }
            }
            timeStamp = 0;
        }else{
            timeStamp = now;
        }
    }

    private class MyHandler extends Handler{
        @Override
        public void handleMessage(Message msg){
            switch (msg.what){
                case MsgCode.INIT:
                    initPlayer();
                    break;
                case MsgCode.PREPARE:
                    duration = mediaPlayer.getDuration();
                    tvDuration.setText(buildTimeMilli(duration));
                    seekBar.setMax((int) duration);
                    mediaPlayer.start();
                    messageView.setText("");
                    break;
                case MsgCode.CHANGE_SIZE:
                    break;
                case MsgCode.SEEK_COMPLETE:

                    break;
                case MsgCode.INFO:
                    switch (msg.arg1){
                        case IMediaPlayer.MEDIA_INFO_BUFFERING_START:
                            bufferView.show(true);
                            break;
                        case IMediaPlayer.MEDIA_INFO_BUFFERING_END:
                            bufferView.show(false);
                            break;
                        case IMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:
                            MyLog.PrintLog(TAG,"size change "+mediaPlayer.getVideoWidth()+" "+mediaPlayer.getVideoHeight());
                            measureHelp.setSize(mediaPlayer.getVideoWidth(),mediaPlayer.getVideoHeight());
                            surfaceView.getHolder().setFixedSize(measureHelp.getWidth(),measureHelp.getHeight());
                            surfaceView.requestLayout();
                            break;
                    }
                    break;
                case MsgCode.ERROR:
                    mediaPlayer.stop();
                    mediaPlayer.release();
                    LemonHello.getWarningHello(getResources().getString(R.string.title_error),"Error info :"+msg.arg1+" , "+msg.arg2)
                            .addAction(new LemonHelloAction(getResources().getString(R.string.exit), new LemonHelloActionDelegate() {
                                @Override
                                public void onClick(LemonHelloView lemonHelloView, LemonHelloInfo lemonHelloInfo, LemonHelloAction lemonHelloAction) {
                                    lemonHelloView.hide();
                                    VideoActivity.this.finish();
                                }
                            }))
                            .addAction(new LemonHelloAction(getResources().getString(R.string.redo), new LemonHelloActionDelegate() {
                                @Override
                                public void onClick(LemonHelloView lemonHelloView, LemonHelloInfo lemonHelloInfo, LemonHelloAction lemonHelloAction) {
                                    lemonHelloView.hide();
                                    initPlayer();
                                }
                            }))
                            .show(VideoActivity.this);
                    break;
                default:
                    MyLog.PrintLog(TAG," handle un-defined message "+msg.what);
                    break;
            }
        }
    }

    private View.OnTouchListener touchListener = new View.OnTouchListener() {
        private Position origin = new Position();
        private Position touch = new Position();
        private Position diff = new Position();
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            switch (motionEvent.getAction()){
                case MotionEvent.ACTION_DOWN:
                    origin.setX(motionEvent.getRawX());
                    origin.setY(motionEvent.getRawY());
                    touch.setX(motionEvent.getRawX());
                    touch.setY(motionEvent.getRawY());
                    diff = touch.minus(origin);

                    break;

                case MotionEvent.ACTION_MOVE:
                    touch.setX(motionEvent.getRawX());
                    touch.setY(motionEvent.getRawY());
                    diff = touch.minus(origin);
                    lytSeek.setVisibility(View.VISIBLE);
                    DisplayMetrics display = getResources().getDisplayMetrics();

                    currentTime = mediaPlayer.getCurrentPosition();
                    float seekTime = currentTime + duration * diff.getX()/display.widthPixels ;
                    tvCurrentPosition.setText(buildTimeMilli((long) seekTime));
                    seekBar.setProgress((int)seekTime);

                    break;

                case MotionEvent.ACTION_UP:
                    lytSeek.setVisibility(View.GONE);
                    if (diff.getX() != 0){
                        mediaPlayer.seekTo(seekBar.getProgress());
                    }
                    break;

            }
            return false;
        }
    };

    public String buildTimeMilli(long duration) {
        long total_seconds = duration / 1000;
        long hours = total_seconds / 3600;
        long minutes = (total_seconds % 3600) / 60;
        long seconds = total_seconds % 60;
        if (duration <= 0) {
            return "--:--";
        }
        if (hours >= 100) {
            return String.format(Locale.US, "%d:%02d:%02d", hours, minutes, seconds);
        } else if (hours > 0) {
            return String.format(Locale.US, "%02d:%02d:%02d", hours, minutes, seconds);
        } else {
            return String.format(Locale.US, "%02d:%02d", minutes, seconds);
        }
    }
}
